#include <iostream>
#include <vector>
#include <chrono>
#include <iterator>
#include <algorithm>
using namespace std;
using namespace std::chrono;

// #define FUNC

#ifdef FUNC
template <typename T>
inline void my_swap(T a, T b) noexcept
{
    T tmp{a};
    a = b;
    b = tmp;
}
#else
// 跟inline函数没啥区别
template <typename T>
struct change
{
    void operator()(T a, T b)
    {
        T tmp{a};
        a = b;
        b = tmp;
    }
};
#endif
// 下面这些结论是用g++ 编译器运行测试的，用clang测试就不一样了
// 慎重 无语
// 自己定义的模板函数不如标准库的（相差很小），
// 标准库的不如直接交换的好（有三倍的差距）
// 像这种简单数值交换还是用简单方法吧
// stl确实强大，自己编写的函数比不上

// 用clang++ -std=c++14编译
// 自定义的函数比标准库要好，运行时间仅为二分之一
// 自定义为直接交换的1.5倍运行时间

// 在windows平台，g++运行时间整体比clang++要长
// 自定义的代码有三倍的差距
// clang对内敛代码优化较好

// 直接比较的代码换用动态内存耗时几近两倍
// 自定义的函数动态比静态慢约七分之一
// 标准库对静态动态处理时间几近相同, 结论:处理对象级别的交换标准库要好
// 动态内存大小对直接代码的比较没有影响

// 在windows上用clang

// #define STL_SWAP
// #define MMY_SWAP
#define MSTATIC
int main()
{
    change<double> my_swap;
#ifdef MSTATIC
    // double t = 9.0, b = 0.0;
    vector<double> t(4,4), b(4,4);
#else
    double *x = new double[500]{2.0, 3.0};
    double *y = new double[500]{4.0, 5.0};
#endif
    steady_clock::time_point t1 = steady_clock::now();
#ifdef STL_SWAP
    for (size_t i = 1000000000; i != 0; --i)
    {
#ifdef MSTATIC
        swap(t, b);
#else
        swap(x[10], y[10]);
#endif
    }
#elif defined(MMY_SWAP)
    for (size_t i = 1000000000; i != 0; --i)
    {
#ifdef MSTATIC
        my_swap(t, b);
#else
        my_swap(x[10], y[10]);
#endif
    }
#else
    // double tmp = 3.0;
    vector<double> tmp(4,4);
    for (size_t i = 1000000000; i != 0; --i)
    {
#ifdef MSTATIC
        tmp = t;
        t = b;
        b = tmp;
#else
        tmp = x[400];
        x[400] = y[400];
        y[400] = tmp;
#endif
    }
#endif
    steady_clock::time_point t2 = steady_clock::now();
    duration<double> dt{duration_cast<duration<double>>(t2 - t1)};
    cout << dt.count() << "\n";
#ifndef MSTATIC
    delete[] x;
    delete[] y;
#endif
    return 0;
}